package both.map.mapView;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.event.EventListenerList;
import javax.swing.event.MouseInputListener;

import both.map.TerrainType;

public class MapDisplay extends JPanel implements MouseInputListener,
		KeyListener {

	private static final long serialVersionUID = 1L;

	private Vector<Chunk> chunks;

	protected EventListenerList listenerList = new EventListenerList();

	private int preX;
	private int preY;
	private boolean keyDown;
	private boolean enabled;

	public MapDisplay() {
		chunks = new Vector<Chunk>();
		this.setPreferredSize(new Dimension(33 * 20, 33 * 20));
		this.setMaximumSize(new Dimension(33 * 20, 33 * 20));
		this.setSize(33 * 20, 33 * 20);
		this.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
		this.addMouseListener(this);
		this.addMouseMotionListener(this);
		this.addKeyListener(this);
		keyDown = false;
		enabled = false;
		preX = -1;
		preY = -1;
		this.setFocusable(true);
	}

	public void createFirstChunk() {
		Chunk chunk1 = new Chunk();
		chunks.add(chunk1);
		repaint();
	}

	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		for (int i = 0; i < chunks.size(); i++) {
			chunks.get(i).draw(g);
		}
	}

	public void updateMap(int chunk, int x, int y, TerrainType change) {
		chunks.get(chunk).updateCell(x, y, change, this.getGraphics());
	}

	public void updateMapArea(int chunk, int x, int y, int a, int b,
			TerrainType change) {		
		for (int i = x; i <= a; i++) {
			for (int j = y; j <= b; j++) {
				updateMap(chunk, i, j, change);
			}
		}
		
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public void addActor(int chunk, Actor actor, int x, int y) {
		chunks.get(chunk).addActor(x, y, actor, this.getGraphics());
	}

	public void moveActor(int chunk, Actor actor, int x, int y) {
		chunks.get(chunk).moveActor(x, y, actor, this.getGraphics());
		repaint();
	}

	// This methods allows classes to register for MyEvents
	public void addMapListener(MapListener listener) {
		listenerList.add(MapListener.class, listener);
	}

	// This methods allows classes to unregister for MyEvents
	public void removeMapListener(MapListener listener) {
		listenerList.remove(MapListener.class, listener);
	}

	// This private class is used to fire MyEvents
	void fireMapEvent(MapEvent evt) {
		if (enabled) {
			Object[] listeners = listenerList.getListenerList();
			// Each listener occupies two elements - the first is the listener
			// class
			// and the second is the listener instance
			for (int i = 0; i < listeners.length; i += 2) {
				if (listeners[i] == MapListener.class) {
					((MapListener) listeners[i + 1]).mapEventPerformed(evt);
				}
			}
		}
	}

	public void setEnabled(boolean e) {
		enabled = e;
	}

	public boolean isEnabled() {
		return enabled;
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		int x = e.getX() / 33;
		int y = e.getY() / 33;
		if (keyDown && x < 20 && y < 20 && x >= 0 && y >= 0) {
			if (preX == -1 && preY == -1) {
				preX = x;
				preY = y;
			} else {
				if (x >= preX && y >= preY) {
					fireMapEvent(new MapEvent(e.getSource(), preX, preY, x, y));
				}
				preX = -1;
				preY = -1;
			}
		}
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		requestFocusInWindow();
	}

	@Override
	public void mouseExited(MouseEvent e) {
	}

	@Override
	public void mousePressed(MouseEvent e) {
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		int x = e.getX() / 33;
		int y = e.getY() / 33;
		if (x < 20 && y < 20 && x >= 0 && y >= 0) {
			fireMapEvent(new MapEvent(e.getSource(), x, y));
		}
	}

	@Override
	public void mouseDragged(MouseEvent e) {
		int x = e.getX() / 33;
		int y = e.getY() / 33;
		if (x < 20 && y < 20 && x >= 0 && y >= 0) {
			fireMapEvent(new MapEvent(e.getSource(), x, y));
		}
	}

	@Override
	public void mouseMoved(MouseEvent e) {
	}

	@Override
	public void keyPressed(KeyEvent e) {
		if (e.isControlDown()) {
			keyDown = true;
		}
	}

	@Override
	public void keyReleased(KeyEvent e) {
		if (!e.isControlDown()) {
			keyDown = false;
			preX = -1;
			preY = -1;
		}
	}

	@Override
	public void keyTyped(KeyEvent e) {
	}
}
